#include "backend.h"
#include "iap/include/iap.h"
#include <string.h>
#include <QDebug>
#include <QTime>
#include <QThread>

#define PRINT_DEBUG_INFO() do {qDebug() << __FILE__ << __LINE__ << __func__;}  while(0)

Backend::Backend()
    : __file()
    , __ioParam1()
    , __ioParam2()
    , __modeSend(false)
    , __modeRecv(false)
    , __modeUdp(false)
    , __modeUart(false)
    , __modeCan(false)
    , __iap(std::bind(&Backend::UpdateToTextArea, this, std::placeholders::_1))
{
    QObject::connect(this, SIGNAL(sig_Exec()), this, SLOT(slo_Exec()));
    QObject::connect(this, SIGNAL(sig_Md5()), this, SLOT(slo_Md5()));
    QObject::connect(this, SIGNAL(sig_OpenIo()), this, SLOT(slo_OpenIo()));
    QObject::connect(this, SIGNAL(sig_CloseIo()), this, SLOT(slo_CloseIo()));
}

void Backend::UpdateToTextArea(QString info)
{
    QString msg;
    info = info.replace('\n', ' ');
    msg = "[" + QTime::currentTime().toString() + "] " + info + "\n";
    emit sig_UpdateProcText(msg);
}

void Backend::slo_Exec()
{
    QThread * thd;
    if (__modeSend) {
        thd = QThread::create([&]() {
            __iap.Send();
            emit sig_ExecDone();
        });
    } else if (__modeRecv) {
        thd = QThread::create([&]() {
            __iap.Recv();
            emit sig_ExecDone();
        });
    }
    thd->start();
}

void Backend::slo_OpenIo()
{
    if (__modeUdp) {
        QStringList strlist = __ioParam1.split(u' ', Qt::SkipEmptyParts);
        QHostAddress localIp(strlist[0]);
        quint16      localPort = strlist[1].toUInt();
        strlist = __ioParam2.split(u' ', Qt::SkipEmptyParts);
        QHostAddress sendIp(strlist[0]);
        quint16      sendPort = strlist[1].toUInt();

        UpdateToTextArea("local IP " + localIp.toString() + ':' + QString("%1").arg(localPort));
        UpdateToTextArea("send  IP " + sendIp.toString()  + ':' + QString("%1").arg(sendPort));
        if (__iap.SetIo(localIp, localPort, sendIp, sendPort)) {
            UpdateToTextArea("\tOK");
        } else {
            UpdateToTextArea("\tERROR");
        }
    }

    UpdateToTextArea("file : " + __file);
    if (__iap.SetHd(__file)) {
        UpdateToTextArea("\tOK");
    } else {
        UpdateToTextArea("\tERROR");
    }
}

void Backend::slo_CloseIo()
{
    __iap.Close();
    UpdateToTextArea("Disconnecting... OK");
}

void Backend::slo_Md5()
{
    if (__iap.SetHd(__file)) {
        QByteArray md5 = __iap.Md5();
        QString md5str("MD5 : ");
        for (auto i : md5) {
            md5str += QString("%1").arg((unsigned char)i, 2, 16, QChar('0'));
        }
        md5str = md5str.toUpper();
        UpdateToTextArea(md5str);
        qDebug() << md5str;
    } else {
        qDebug() << "md5 error";
    }
}

QString Backend::ToHexString(quint8 * data, qint32 len)
{
    QString str;
    for (int i  = 0; i < len; ++i) {
        str += QString("%1 ").arg((unsigned char)data[i], 2, 16, QChar('0'));
    }
    str = str.toUpper();
    return std::move(str);
}
